/**
 * 标注图层类
 * 在矢量要素上显示文本标注
 */

import { Map as OlMap } from 'ol';
import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import { Feature } from 'ol';
import { Geometry, Point, LineString, Polygon } from 'ol/geom';
import { BaseLayer } from './BaseLayer';
import { LabelLayerOptions, FeatureData, Coordinate } from '../types';
import { DataUtil } from '../utils/data';
import { StyleUtil } from '../utils/style';
import { Style, Text, Fill, Stroke } from 'ol/style';

/**
 * 标注图层类
 */
export class LabelLayer extends BaseLayer {
  /** 图层配置 */
  protected options: LabelLayerOptions;
  /** 矢量数据源 */
  private source: VectorSource<Feature<Geometry>> | null = null;
  /** 基础矢量图层（用于显示要素） */
  private baseVectorLayer: VectorLayer<VectorSource<Feature<Geometry>>> | null = null;

  /**
   * 构造函数
   * @param options 图层配置
   */
  constructor(options: LabelLayerOptions = {}) {
    super(options);
    this.options = {
      showLabel: true,
      textField: 'name',
      offset: [0, -10],
      textAlign: 'center',
      textBaseline: 'bottom',
      ...options
    };
  }

  /**
   * 创建图层
   */
  protected createLayer(): void {
    this.source = new VectorSource<Feature<Geometry>>();

    // 创建标注图层（只显示文本）
    this.layer = new VectorLayer({
      source: this.source,
      style: (feature) => this.getLabelStyle(feature as Feature<Geometry>)
    });

    // 如果需要显示要素本身，创建基础矢量图层
    if (this.map) {
      this.baseVectorLayer = new VectorLayer({
        source: this.source,
        style: (feature) => this.getFeatureStyle(feature as Feature<Geometry>)
      });
      this.map.addLayer(this.baseVectorLayer);
    }
  }

  /**
   * 获取标注样式
   * @param feature 要素
   * @returns 样式
   */
  private getLabelStyle(feature: Feature<Geometry>): Style | Style[] | undefined {
    if (!this.options.showLabel) {
      return undefined;
    }

    const textField = this.options.textField || 'name';
    const text = feature.get(textField) || feature.getId() || '';

    if (!text) {
      return undefined;
    }

    const geometry = feature.getGeometry();
    if (!geometry) {
      return undefined;
    }

    // 根据几何类型确定标注位置
    let coordinates: [number, number];
    if (geometry instanceof Point) {
      coordinates = geometry.getCoordinates() as [number, number];
    } else if (geometry instanceof LineString || geometry instanceof Polygon) {
      // 对于线和面，使用中心点
      const extent = geometry.getExtent();
      coordinates = [
        (extent[0] + extent[2]) / 2,
        (extent[1] + extent[3]) / 2
      ];
    } else {
      return undefined;
    }

    // 使用自定义样式或默认样式
    if (this.options.labelStyle) {
      return this.options.labelStyle;
    }

    return new Style({
      text: new Text({
        text: String(text),
        offsetX: this.options.offset?.[0] || 0,
        offsetY: this.options.offset?.[1] || -10,
        textAlign: this.options.textAlign || 'center',
        textBaseline: this.options.textBaseline || 'bottom',
        fill: new Fill({
          color: '#000'
        }),
        stroke: new Stroke({
          color: '#fff',
          width: 3
        }),
        font: '12px sans-serif'
      })
    });
  }

  /**
   * 获取要素样式（用于显示要素本身）
   * @param feature 要素
   * @returns 样式
   */
  private getFeatureStyle(feature: Feature<Geometry>): Style {
    const geometry = feature.getGeometry();
    if (!geometry) {
      return new Style();
    }

    if (geometry instanceof Point) {
      return StyleUtil.createCircleStyle({
        radius: 5,
        fillColor: '#3399CC',
        strokeColor: '#fff',
        strokeWidth: 2
      });
    } else if (geometry instanceof LineString) {
      return StyleUtil.createLineStyle({
        color: '#3399CC',
        width: 2
      });
    } else if (geometry instanceof Polygon) {
      return StyleUtil.createPolygonStyle({
        fillColor: 'rgba(51, 153, 204, 0.3)',
        strokeColor: '#3399CC',
        strokeWidth: 2
      });
    }

    return new Style();
  }

  /**
   * 添加要素
   * @param data 要素数据
   */
  addFeature(data: FeatureData): void {
    if (!this.source) {
      throw new Error('Layer not initialized');
    }

    const feature = DataUtil.createFeatureFromData(data);
    if (data.id !== undefined) {
      feature.setId(data.id);
    }
    this.source.addFeature(feature);
    this.emit('featureadd', feature);
  }

  /**
   * 批量添加要素
   * @param dataList 要素数据数组
   */
  addFeatures(dataList: FeatureData[]): void {
    if (!this.source) {
      throw new Error('Layer not initialized');
    }

    const features = dataList.map(data => {
      const feature = DataUtil.createFeatureFromData(data);
      if (data.id !== undefined) {
        feature.setId(data.id);
      }
      return feature;
    });

    this.source.addFeatures(features);
    this.emit('featuresadd', features);
  }

  /**
   * 移除要素
   * @param featureId 要素ID
   */
  removeFeature(featureId: string | number): void {
    if (!this.source) return;

    const feature = this.source.getFeatureById(featureId);
    if (feature && feature instanceof Feature) {
      this.source.removeFeature(feature);
      this.emit('featureremove', feature);
    }
  }

  /**
   * 清空所有要素
   */
  clearFeatures(): void {
    if (this.source) {
      this.source.clear();
      this.emit('featuresclear');
    }
  }

  /**
   * 更新数据
   * @param dataList 要素数据数组
   */
  updateData(dataList: FeatureData[]): void {
    this.clearFeatures();
    this.addFeatures(dataList);
  }

  /**
   * 设置标注字段
   * @param fieldName 字段名
   */
  setTextField(fieldName: string): void {
    this.options.textField = fieldName;
    if (this.layer) {
      (this.layer as any).setStyle((feature: any) => this.getLabelStyle(feature as Feature<Geometry>));
    }
  }

  /**
   * 设置是否显示标注
   * @param show 是否显示
   */
  setShowLabel(show: boolean): void {
    this.options.showLabel = show;
    if (this.layer) {
      (this.layer as any).setStyle((feature: any) => this.getLabelStyle(feature as Feature<Geometry>));
    }
  }

  /**
   * 销毁图层
   */
  destroy(): void {
    if (this.map && this.baseVectorLayer) {
      this.map.removeLayer(this.baseVectorLayer);
      this.baseVectorLayer = null;
    }
    super.destroy();
  }
}

